package lapsnake.model;

import java.awt.Color;
import java.awt.Image;
import java.beans.PropertyVetoException;
import java.util.HashMap;

import javax.swing.ImageIcon;

import lapsnake.model.data.ChildField;
import lapsnake.model.expr.*;
import lapsnake.model.misc.*;
import lapsnake.model.stmt.*;
import lapsnake.ui.IconLib;

public class NodeRegister
{	
	private static final HashMap<Class<? extends LapNode>, String> readableNames = new HashMap<>();
	private static final HashMap<Class<? extends LapNode>, String> iconNames = new HashMap<>();
	private static final HashMap<Class<? extends LapNode>, Color> nodeColor = new HashMap<>();
	private static final HashMap<Class<? extends LapNode>, DefaultNodeSpawner<? extends LapNode>> defaults = new HashMap<>();
	
	static
	{
		readableNames.put(LapModule.class, "Module");
		readableNames.put(LapExpression.class, "Expression");
		readableNames.put(LapStatement.class, "Statement");
		readableNames.put(LapAbstractSlice.class, "Slice");
		
		iconNames.put(LapExpression.class, "expr");
		iconNames.put(LapStatement.class, "stmt");
		iconNames.put(LapAbstractSlice.class, "slice");
		iconNames.put(LapName.class, "name");
		iconNames.put(LapComprehension.class, "comprehension");
		iconNames.put(LapArguments.class, "arguments");
		iconNames.put(LapExcepthandler.class, "except");
		iconNames.put(LapKeyword.class, "keyword");
		iconNames.put(LapAlias.class, "alias");

		iconNames.put(LapImport.class, "import");
		iconNames.put(LapImportFrom.class, "importFrom");
		iconNames.put(LapAlias.class, "alias");
		
		iconNames.put(LapIf.class, "if");
		iconNames.put(LapFor.class, "for");
		iconNames.put(LapWhile.class, "while");
		iconNames.put(LapIfExp.class, "ifExp");
		
		iconNames.put(LapGeneratorExp.class, "generator");
		iconNames.put(LapRaise.class, "raise");
		
		iconNames.put(LapAssign.class, "assign");
		iconNames.put(LapPrint.class, "print");
		
		iconNames.put(LapAttribute.class, "attribute");

		iconNames.put(LapNum.class, "num");
		iconNames.put(LapStr.class, "str");
		iconNames.put(LapTuple.class, "tuple");
		iconNames.put(LapList.class, "list");
		iconNames.put(LapDict.class, "dictionary");
		iconNames.put(LapKeyword.class, "keyword");
		
		iconNames.put(LapBreak.class, "break");
		iconNames.put(LapContinue.class, "continue");
		iconNames.put(LapReturn.class, "return");
		iconNames.put(LapDelete.class, "delete");
		iconNames.put(LapPass.class, "pass");
		
		nodeColor.put(LapExpression.class, new Color(0xb1ffb6));
		nodeColor.put(LapStatement.class, new Color(0xfcff92));
		nodeColor.put(LapAbstractSlice.class, new Color(0xf3d0ff));
		nodeColor.put(LapName.class, new Color(0xb9efff));
		nodeColor.put(LapComprehension.class, new Color(0xffc770));
		nodeColor.put(LapArguments.class, new Color(0xa2b5ff));
		nodeColor.put(LapExcepthandler.class, new Color(0xff5151));
		nodeColor.put(LapKeyword.class, new Color(0x63a7ff));
		nodeColor.put(LapAlias.class, new Color(0xbbbbbb));
		
		/*defaults.put(LapExpression.class, new Color(0xb1ffb6));
		defaults.put(LapStatement.class, new Color(0xfcff92));
		defaults.put(LapAbstractSlice.class, new Color(0xf3d0ff));
		defaults.put(LapName.class, new Color(0xb9efff));
		defaults.put(LapComprehension.class, new Color(0xffc770));
		defaults.put(LapArguments.class, new Color(0xa2b5ff));
		defaults.put(LapExcepthandler.class, new Color(0xff5151));*/
		defaults.put(LapAlias.class, new DefaultNodeSpawner<LapAlias>()
		{
			@Override
			public LapAlias spawn(PyAST pyAST, 
				ChildField<? super LapAlias> parentField) throws PropertyVetoException
			{
				return new LapAlias(pyAST, parentField, "myModule");
			}
		});
	}
	public static<X extends LapNode> X getDefaultNode(PyAST pyAST, ChildField<? super X> parentField) throws PropertyVetoException
	{
		Class<? super X> type = parentField.getType();
		@SuppressWarnings("unchecked")
		DefaultNodeSpawner<X> spawner = (DefaultNodeSpawner<X>) defaults.get(type);
		assert spawner != null : "No spawner registered for: "+type+"!";
		X inst = spawner.spawn(pyAST, parentField);
		assert type.isInstance(inst);
		return inst;
	}
	
	public static String getReadableName(Class<? extends LapNode> type)
	{
		return readableNames.getOrDefault(type, type.getSimpleName().substring(3));
	}
	public static Color getNodeColor(Class<? extends LapNode> type)
	{
		Class<?> t = type;
		while(t != LapNode.class)
		{
			Color c = nodeColor.get(t);
			if(c != null)
				return c;
			t = t.getSuperclass();
		}
		return null;
	}

	public static Image getImage(Class<? extends LapNode> type, String iconType)
	{
		String n = null;
		Class<?> t = type;
		while(t != LapNode.class)
		{
			n = iconNames.get(t);
			if(n != null)
			{
				ImageIcon im = IconLib.get(n+iconType);
				if(im != null)
					return im.getImage();
			}
			t = t.getSuperclass();
		}
		return null;
	}
}
